package com.local.videoplayer.player;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.provider.Settings;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import com.local.videoplayer.R;
import java.lang.reflect.Constructor;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by Nathen on 16/7/30.
 */
public abstract class MyVideoPlayer extends FrameLayout
        implements View.OnClickListener, SeekBar.OnSeekBarChangeListener,
        View.OnTouchListener
{

	public static final String TAG = "JieCaoVideoPlayer";

	protected boolean isVideoRendingStart = false;
	public static boolean ACTION_BAR_EXIST = true;
	public static boolean TOOL_BAR_EXIST = true;
	public static int FULLSCREEN_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
	public static int NORMAL_ORIENTATION = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
	public static boolean SAVE_PROGRESS = true;

	public static boolean WIFI_TIP_DIALOG_SHOWED = false;

	public static final int FULLSCREEN_ID = 33797;
	public static final int TINY_ID = 33798;
	public static final int THRESHOLD = 80;
	public static final int FULL_SCREEN_NORMAL_DELAY = 300;
	public static long CLICK_QUIT_FULLSCREEN_TIME = 0;

	public static final int SCREEN_LAYOUT_NORMAL = 0;
	public static final int SCREEN_LAYOUT_LIST = 1;
	public static final int SCREEN_WINDOW_FULLSCREEN = 2;
	public static final int SCREEN_WINDOW_TINY = 3;

	public static final int CURRENT_STATE_NORMAL = 0;
	public static final int CURRENT_STATE_PREPARING = 1;
	public static final int CURRENT_STATE_PREPARING_CHANGING_URL = 2;
	public static final int CURRENT_STATE_PLAYING = 3;
	public static final int CURRENT_STATE_PLAYING_BUFFERING_START = 4;
	public static final int CURRENT_STATE_PAUSE = 5;
	public static final int CURRENT_STATE_AUTO_COMPLETE = 6;
	public static final int CURRENT_STATE_ERROR = 7;

	public static int BACKUP_PLAYING_BUFFERING_STATE = -1;

	public int currentState = -1;
	public int currentScreen = -1;
	public boolean loop = false;
	public Map<String, String> headData;

	// public String url = "";
	public Object[] objects = null;
	public int seekToInAdvance = 0;

	public ImageView startButton;
	public SeekBar progressBar;
	public TextView currentTimeTextView, totalTimeTextView;
	public ViewGroup textureViewContainer;
	public ViewGroup topContainer, bottomContainer;

	protected static UserAction JC_USER_EVENT;
	protected static Timer UPDATE_PROGRESS_TIMER;

	protected int mScreenWidth;
	protected int mScreenHeight;
	protected AudioManager mAudioManager;
	protected Handler mHandler;
	protected ProgressTimerTask mProgressTimerTask;

	protected boolean mTouchingProgressBar;
	protected float mDownX;
	protected float mDownY;
	protected boolean mChangeVolume;
	protected boolean mChangePosition;
	protected boolean mChangeBrightness;
	protected int mGestureDownPosition;
	protected int mGestureDownVolume;
	protected float mGestureDownBrightness;
	protected int mSeekTimePosition;

	public MyVideoPlayer(Context context)
	{
		super(context);
		init(context);
	}

	public MyVideoPlayer(Context context, AttributeSet attrs)
	{
		super(context, attrs);
		init(context);
	}

	public abstract int getLayoutId();

	public void init(Context context)
	{
		View.inflate(context, getLayoutId(), this);
		startButton = (ImageView) findViewById(R.id.start);
		progressBar = (SeekBar) findViewById(R.id.bottom_seek_progress);
		currentTimeTextView = (TextView) findViewById(R.id.current);
		totalTimeTextView = (TextView) findViewById(R.id.total);
		bottomContainer = (ViewGroup) findViewById(R.id.layout_bottom);
		textureViewContainer = (ViewGroup) findViewById(R.id.surface_container);
		topContainer = (ViewGroup) findViewById(R.id.layout_top);

		startButton.setOnClickListener(this);
		progressBar.setOnSeekBarChangeListener(this);
		bottomContainer.setOnClickListener(this);
		textureViewContainer.setOnClickListener(this);
		textureViewContainer.setOnTouchListener(this);

		mScreenWidth = getContext().getResources()
		        .getDisplayMetrics().widthPixels;
		mScreenHeight = getContext().getResources()
		        .getDisplayMetrics().heightPixels;
		mAudioManager = (AudioManager) getContext()
		        .getSystemService(Context.AUDIO_SERVICE);
		mHandler = new Handler();

		try
		{
			if (isCurrentJcvd())
			{
				NORMAL_ORIENTATION = ((AppCompatActivity) context)
				        .getRequestedOrientation();
			}
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public void setUp(String url, int screen, Object... objects)
	{
		LinkedHashMap map = new LinkedHashMap();
		map.put(URL_KEY_DEFAULT, url);
		setUp(map, 0, screen, objects);
	}

	LinkedHashMap urlMap;
	int currentUrlMapIndex = 0;

	public static final String URL_KEY_DEFAULT = "URL_KEY_DEFAULT";

	public void setUp(LinkedHashMap urlMap, int defaultUrlMapIndex, int screen,
	        Object... objects)
	{
		if (this.urlMap != null
		        && !TextUtils.isEmpty(VideoUtils.getCurrentUrlFromMap(urlMap,
		                currentUrlMapIndex))
		        && TextUtils.equals(
		                VideoUtils.getCurrentUrlFromMap(this.urlMap,
		                        currentUrlMapIndex),
		                VideoUtils.getCurrentUrlFromMap(urlMap,
		                        currentUrlMapIndex)))
		{
			return;
		}
		this.urlMap = urlMap;
		this.currentUrlMapIndex = defaultUrlMapIndex;
		this.currentScreen = screen;
		this.objects = objects;
		this.headData = null;
		isVideoRendingStart = false;
		onStateNormal();
	}

	@Override
	public void onClick(View v)
	{
		int i = v.getId();
		if (i == R.id.start)
		{
			Log.i(TAG, "onClick start [" + this.hashCode() + "] ");
			if (TextUtils.isEmpty(VideoUtils.getCurrentUrlFromMap(urlMap,
			        currentUrlMapIndex)))
			{
				Toast.makeText(getContext(),
				        getResources().getString(R.string.no_url),
				        Toast.LENGTH_SHORT).show();
				return;
			}
			if (currentState == CURRENT_STATE_NORMAL
			        || currentState == CURRENT_STATE_ERROR)
			{
				if (!VideoUtils.getCurrentUrlFromMap(urlMap, currentUrlMapIndex)
				        .startsWith("file")
				        && !VideoUtils.getCurrentUrlFromMap(urlMap,
				                currentUrlMapIndex).startsWith("/")
				        && !VideoUtils.isWifiConnected(getContext())
				        && !WIFI_TIP_DIALOG_SHOWED)
				{
					showWifiDialog(UserActionStandard.ON_CLICK_START_ICON);
					return;
				}
				startVideo();
				onEvent(currentState != CURRENT_STATE_ERROR
				        ? UserAction.ON_CLICK_START_ICON
				        : UserAction.ON_CLICK_START_ERROR);
			}
			else if (currentState == CURRENT_STATE_PLAYING)
			{
				onEvent(UserAction.ON_CLICK_PAUSE);
				Log.d(TAG, "pauseVideo [" + this.hashCode() + "] ");
				MediaManager.instance(getContext()).mMediaPlayer.pause();
				onStatePause();
			}
			else if (currentState == CURRENT_STATE_PAUSE)
			{
				onEvent(UserAction.ON_CLICK_RESUME);
				MediaManager.instance(getContext()).mMediaPlayer.start();
				onStatePlaying();
			}
			else if (currentState == CURRENT_STATE_AUTO_COMPLETE)
			{
				onEvent(UserAction.ON_CLICK_START_AUTO_COMPLETE);
				startVideo();
			}
		}
		else if (i == R.id.fullscreen)
		{
			Log.i(TAG, "onClick fullscreen [" + this.hashCode() + "] ");
			if (currentState == CURRENT_STATE_AUTO_COMPLETE)
				return;
			if (currentScreen == SCREEN_WINDOW_FULLSCREEN)
			{
				// quit fullscreen
				backPress();
			}
			else
			{
				Log.d(TAG, "toFullscreenActivity [" + this.hashCode() + "] ");
				onEvent(UserAction.ON_ENTER_FULLSCREEN);
				startWindowFullscreen();
			}
		}
		else if (i == R.id.surface_container
		        && currentState == CURRENT_STATE_ERROR)
		{
			Log.i(TAG, "onClick surfaceContainer State=Error ["
			        + this.hashCode() + "] ");
			startVideo();
		}
	}

	@Override
	public boolean onTouch(View v, MotionEvent event)
	{
		float x = event.getX();
		float y = event.getY();
		int id = v.getId();
		if (id == R.id.surface_container)
		{
			switch (event.getAction())
			{
				case MotionEvent.ACTION_DOWN:
					Log.i(TAG, "onTouch surfaceContainer actionDown ["
					        + this.hashCode() + "] ");
					mTouchingProgressBar = true;

					mDownX = x;
					mDownY = y;
					mChangeVolume = false;
					mChangePosition = false;
					mChangeBrightness = false;
					break;
				case MotionEvent.ACTION_MOVE:
					Log.i(TAG, "onTouch surfaceContainer actionMove ["
					        + this.hashCode() + "] ");
					float deltaX = x - mDownX;
					float deltaY = y - mDownY;
					float absDeltaX = Math.abs(deltaX);
					float absDeltaY = Math.abs(deltaY);
					if (currentScreen == SCREEN_WINDOW_FULLSCREEN)
					{
						if (!mChangePosition && !mChangeVolume
						        && !mChangeBrightness)
						{
							if (absDeltaX > THRESHOLD || absDeltaY > THRESHOLD)
							{
								cancelProgressTimer();
								if (absDeltaX >= THRESHOLD)
								{
									// 全屏模式下的CURRENT_STATE_ERROR状态下,不响应进度拖动事件.
									// 否则会因为mediaplayer的状态非法导致App Crash
									if (currentState != CURRENT_STATE_ERROR)
									{
										mChangePosition = true;
										mGestureDownPosition = getCurrentPositionWhenPlaying();
									}
								}
								else
								{
									// 如果y轴滑动距离超过设置的处理范围，那么进行滑动事件处理
									if (mDownX < mScreenWidth * 0.5f)
									{// 左侧改变亮度
										mChangeBrightness = true;
										WindowManager.LayoutParams lp = VideoUtils
										        .getAppCompActivity(
										                getContext())
										        .getWindow().getAttributes();
										if (lp.screenBrightness < 0)
										{
											try
											{
												mGestureDownBrightness = Settings.System
												        .getInt(getContext()
												                .getContentResolver(),
												                Settings.System.SCREEN_BRIGHTNESS);
												Log.i(TAG,
												        "current system brightness: "
												                + mGestureDownBrightness);
											} catch (Settings.SettingNotFoundException e)
											{
												e.printStackTrace();
											}
										}
										else
										{
											mGestureDownBrightness = lp.screenBrightness
											        * 255;
											Log.i(TAG,
											        "current activity brightness: "
											                + mGestureDownBrightness);
										}
									}
									else
									{// 右侧改变声音
										mChangeVolume = true;
										mGestureDownVolume = mAudioManager
										        .getStreamVolume(
										                AudioManager.STREAM_MUSIC);
									}
								}
							}
						}
					}
					if (mChangePosition)
					{
						int totalTimeDuration = getDuration();
						mSeekTimePosition = (int) (mGestureDownPosition
						        + deltaX * totalTimeDuration / mScreenWidth);
						if (mSeekTimePosition > totalTimeDuration)
							mSeekTimePosition = totalTimeDuration;
						String seekTime = VideoUtils
						        .stringForTime(mSeekTimePosition);
						String totalTime = VideoUtils
						        .stringForTime(totalTimeDuration);

						showProgressDialog(deltaX, seekTime, mSeekTimePosition,
						        totalTime, totalTimeDuration);
					}
					if (mChangeVolume)
					{
						deltaY = -deltaY;
						int max = mAudioManager
						        .getStreamMaxVolume(AudioManager.STREAM_MUSIC);
						int deltaV = (int) (max * deltaY * 3 / mScreenHeight);
						mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
						        mGestureDownVolume + deltaV, 0);
						// dialog中显示百分比
						int volumePercent = (int) (mGestureDownVolume * 100
						        / max + deltaY * 3 * 100 / mScreenHeight);
						showVolumeDialog(-deltaY, volumePercent);
					}

					if (mChangeBrightness)
					{
						deltaY = -deltaY;
						int deltaV = (int) (255 * deltaY * 3 / mScreenHeight);
						WindowManager.LayoutParams params = VideoUtils
						        .getAppCompActivity(getContext()).getWindow()
						        .getAttributes();
						if (((mGestureDownBrightness + deltaV) / 255) >= 1)
						{// 这和声音有区别，必须自己过滤一下负值
							params.screenBrightness = 1;
						}
						else if (((mGestureDownBrightness + deltaV) / 255) <= 0)
						{
							params.screenBrightness = 0.01f;
						}
						else
						{
							params.screenBrightness = (mGestureDownBrightness
							        + deltaV) / 255;
						}
						VideoUtils.getAppCompActivity(getContext()).getWindow()
						        .setAttributes(params);
						// dialog中显示百分比
						int brightnessPercent = (int) (mGestureDownBrightness
						        * 100 / 255 + deltaY * 3 * 100 / mScreenHeight);
						showBrightnessDialog(brightnessPercent);
						// mDownY = y;
					}
					break;
				case MotionEvent.ACTION_UP:
					Log.i(TAG, "onTouch surfaceContainer actionUp ["
					        + this.hashCode() + "] ");
					mTouchingProgressBar = false;
					dismissProgressDialog();
					dismissVolumeDialog();
					dismissBrightnessDialog();
					if (mChangePosition)
					{
						onEvent(UserAction.ON_TOUCH_SCREEN_SEEK_POSITION);
						MediaManager.instance(getContext()).mMediaPlayer
						        .seekTo(mSeekTimePosition);
						int duration = getDuration();
						int progress = mSeekTimePosition * 100
						        / (duration == 0 ? 1 : duration);
						progressBar.setProgress(progress);
					}
					if (mChangeVolume)
					{
						onEvent(UserAction.ON_TOUCH_SCREEN_SEEK_VOLUME);
					}
					startProgressTimer();
					break;
			}
		}
		return false;
	}

	public void startVideo()
	{
		VideoPlayerManager.completeAll();
		Log.d(TAG, "startVideo [" + this.hashCode() + "] ");
		initTextureView();
		addTextureView();
		AudioManager mAudioManager = (AudioManager) getContext()
		        .getSystemService(Context.AUDIO_SERVICE);
		mAudioManager.requestAudioFocus(onAudioFocusChangeListener,
		        AudioManager.STREAM_MUSIC,
		        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
		VideoUtils.scanForActivity(getContext()).getWindow()
		        .addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		MediaManager.CURRENT_PLAYING_URL = VideoUtils
		        .getCurrentUrlFromMap(urlMap, currentUrlMapIndex);
		MediaManager.CURRENT_PLING_LOOP = loop;
		MediaManager.MAP_HEADER_DATA = headData;
		onStatePreparing();
		VideoPlayerManager.setFirstFloor(this);
	}

	public void onVideoRendingStart()
	{
		Log.i(TAG, "onVideoRendingStart " + " [" + this.hashCode() + "] ");
		isVideoRendingStart = true;
		if (currentState != CURRENT_STATE_PREPARING
		        && currentState != CURRENT_STATE_PREPARING_CHANGING_URL
		        && currentState != CURRENT_STATE_PLAYING_BUFFERING_START)
			return;
		if (seekToInAdvance != 0)
		{
			MediaManager.instance(getContext()).mMediaPlayer
			        .seekTo(seekToInAdvance);
			seekToInAdvance = 0;
		}
		else
		{
			int position = VideoUtils.getSavedProgress(getContext(), VideoUtils
			        .getCurrentUrlFromMap(urlMap, currentUrlMapIndex));
			if (position != 0)
			{
				MediaManager.instance(getContext()).mMediaPlayer
				        .seekTo(position);
			}
		}
		startProgressTimer();
		onStatePlaying();
	}

	public void setState(int state)
	{
		setState(state, 0, 0);
	}

	public void setState(int state, int urlMapIndex, int seekToInAdvance)
	{
		switch (state)
		{
			case CURRENT_STATE_NORMAL:
				onStateNormal();
				break;
			case CURRENT_STATE_PREPARING:
				onStatePreparing();
				break;
			case CURRENT_STATE_PREPARING_CHANGING_URL:
				onStatePreparingChangingUrl(urlMapIndex, seekToInAdvance);
				break;
			case CURRENT_STATE_PLAYING:
				onStatePlaying();
				break;
			case CURRENT_STATE_PAUSE:
				onStatePause();
				break;
			case CURRENT_STATE_PLAYING_BUFFERING_START:
				onStatePlaybackBufferingStart();
				break;
			case CURRENT_STATE_ERROR:
				onStateError();
				break;
			case CURRENT_STATE_AUTO_COMPLETE:
				onStateAutoComplete();
				break;
		}
	}

	public void onStateNormal()
	{
		Log.i(TAG, "onStateNormal " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_NORMAL;
		cancelProgressTimer();
		if (isCurrentJcvd())
		{// 这个if是无法取代的，否则进入全屏的时候会releaseMediaPlayer
			MediaManager.instance(getContext()).releaseMediaPlayer();
		}
	}

	public void onStatePreparing()
	{
		Log.i(TAG, "onStatePreparing " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_PREPARING;
		resetProgressAndTime();
	}

	public void onStatePreparingChangingUrl(int urlMapIndex,
	        int seekToInAdvance)
	{
		currentState = CURRENT_STATE_PREPARING_CHANGING_URL;
		this.currentUrlMapIndex = urlMapIndex;
		this.seekToInAdvance = seekToInAdvance;
		initTextureView();
		addTextureView();
		MediaManager.CURRENT_PLAYING_URL = VideoUtils
		        .getCurrentUrlFromMap(urlMap, this.currentUrlMapIndex);
		MediaManager.CURRENT_PLING_LOOP = this.loop;
		MediaManager.MAP_HEADER_DATA = this.headData;
		MediaManager.instance(getContext()).prepare();
	}

	public void onStatePlaying()
	{
		Log.i(TAG, "onStatePlaying " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_PLAYING;
		startProgressTimer();
	}

	public void onStatePause()
	{
		Log.i(TAG, "onStatePause " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_PAUSE;
		startProgressTimer();
	}

	public void onStatePlaybackBufferingStart()
	{
		Log.i(TAG, "onStatePlaybackBufferingStart " + " [" + this.hashCode()
		        + "] ");
		currentState = CURRENT_STATE_PLAYING_BUFFERING_START;
		startProgressTimer();
	}

	public void onStateError()
	{
		Log.i(TAG, "onStateError " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_ERROR;
		cancelProgressTimer();
	}

	public void onStateAutoComplete()
	{
		Log.i(TAG, "onStateAutoComplete " + " [" + this.hashCode() + "] ");
		currentState = CURRENT_STATE_AUTO_COMPLETE;
		cancelProgressTimer();
		progressBar.setProgress(100);
		currentTimeTextView.setText(totalTimeTextView.getText());
	}

	public void onInfo(int what, int extra)
	{
		Log.d(TAG, "onInfo what - " + what + " extra - " + extra);
		if (what == MediaPlayer.MEDIA_INFO_BUFFERING_START)
		{
			if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START)
				return;
			BACKUP_PLAYING_BUFFERING_STATE = currentState;
			onStatePlaybackBufferingStart();
			Log.d(TAG, "MEDIA_INFO_BUFFERING_START");
		}
		else if (what == MediaPlayer.MEDIA_INFO_BUFFERING_END)
		{
			if (BACKUP_PLAYING_BUFFERING_STATE != -1)
			{
				if (currentState == CURRENT_STATE_PLAYING_BUFFERING_START)
				{
					setState(BACKUP_PLAYING_BUFFERING_STATE);
				}
				BACKUP_PLAYING_BUFFERING_STATE = -1;
			}
			Log.d(TAG, "MEDIA_INFO_BUFFERING_END");
		}
		else if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START)
		{
			Log.d(TAG, "MEDIA_INFO_VIDEO_RENDERING_START");
			onVideoRendingStart();
		}
	}

	public void onError(int what, int extra)
	{
		Log.e(TAG, "onError " + what + " - " + extra + " [" + this.hashCode()
		        + "] ");
		if (what != 38 && what != -38 && extra != -38)
		{
			onStateError();
			if (isCurrentJcvd())
			{
				MediaManager.instance(getContext()).releaseMediaPlayer();
			}
		}
	}

	public int widthRatio = 0;
	public int heightRatio = 0;

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		if (currentScreen == SCREEN_WINDOW_FULLSCREEN
		        || currentScreen == SCREEN_WINDOW_TINY)
		{
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
			return;
		}
		if (widthRatio != 0 && heightRatio != 0)
		{
			int specWidth = MeasureSpec.getSize(widthMeasureSpec);
			int specHeight = (int) ((specWidth * (float) heightRatio)
			        / widthRatio);
			setMeasuredDimension(specWidth, specHeight);

			int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(specWidth,
			        MeasureSpec.EXACTLY);
			int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight,
			        MeasureSpec.EXACTLY);
			getChildAt(0).measure(childWidthMeasureSpec,
			        childHeightMeasureSpec);
		}
		else
		{
			super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		}

	}

	public void onAutoCompletion()
	{
		// 加上这句，避免循环播放video的时候，内存不断飙升。
		Runtime.getRuntime().gc();
		Log.i(TAG, "onAutoCompletion " + " [" + this.hashCode() + "] ");
		onEvent(UserAction.ON_AUTO_COMPLETE);
		dismissVolumeDialog();
		dismissProgressDialog();
		dismissBrightnessDialog();
		cancelProgressTimer();
		onStateAutoComplete();

		if (currentScreen == SCREEN_WINDOW_FULLSCREEN)
		{
			backPress();
		}
		VideoUtils.saveProgress(getContext(),
		        VideoUtils.getCurrentUrlFromMap(urlMap, currentUrlMapIndex), 0);
	}

	public void onCompletion()
	{
		Log.i(TAG, "onCompletion " + " [" + this.hashCode() + "] ");
		// save position
		if (currentState == CURRENT_STATE_PLAYING
		        || currentState == CURRENT_STATE_PAUSE)
		{
			int position = getCurrentPositionWhenPlaying();
			// int duration = getDuration();
			VideoUtils.saveProgress(getContext(),
			        VideoUtils.getCurrentUrlFromMap(urlMap, currentUrlMapIndex),
			        position);
		}
		cancelProgressTimer();
		onStateNormal();
		// 清理缓存变量
		textureViewContainer.removeView(MediaManager.textureView);
		MediaManager.instance(getContext()).currentVideoWidth = 0;
		MediaManager.instance(getContext()).currentVideoHeight = 0;

		AudioManager mAudioManager = (AudioManager) getContext()
		        .getSystemService(Context.AUDIO_SERVICE);
		mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
		VideoUtils.scanForActivity(getContext()).getWindow()
		        .clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		clearFullscreenLayout();
		VideoUtils.getAppCompActivity(getContext())
		        .setRequestedOrientation(NORMAL_ORIENTATION);

		MediaManager.textureView = null;
		MediaManager.savedSurfaceTexture = null;
		isVideoRendingStart = false;
	}

	public void release()
	{
		if (VideoUtils.getCurrentUrlFromMap(urlMap, currentUrlMapIndex)
		        .equals(MediaManager.CURRENT_PLAYING_URL)
		        && (System.currentTimeMillis()
		                - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY)
		{
			// 在非全屏的情况下只能backPress()
			if (VideoPlayerManager.getSecondFloor() != null
			        && VideoPlayerManager
			                .getSecondFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN)
			{// 点击全屏
			}
			else if (VideoPlayerManager.getSecondFloor() == null
			        && VideoPlayerManager.getFirstFloor() != null
			        && VideoPlayerManager
			                .getFirstFloor().currentScreen == SCREEN_WINDOW_FULLSCREEN)
			{// 直接全屏
			}
			else
			{
				Log.d(TAG, "release [" + this.hashCode() + "]");
				releaseAllVideos();
			}
		}
	}

	public void releaseAllVideos()
	{
		if ((System.currentTimeMillis()
		        - CLICK_QUIT_FULLSCREEN_TIME) > FULL_SCREEN_NORMAL_DELAY)
		{
			Log.d(TAG, "releaseAllVideos");
			VideoPlayerManager.completeAll();
			MediaManager.instance(getContext()).releaseMediaPlayer();
		}
	}

	public void initTextureView()
	{
		removeTextureView();
		MediaManager.textureView = new ResizeTextureView(getContext());
		MediaManager.textureView
		        .setSurfaceTextureListener(MediaManager.instance(getContext()));
	}

	public void addTextureView()
	{
		Log.d(TAG, "addTextureView [" + this.hashCode() + "] ");
		LayoutParams layoutParams = new LayoutParams(
		        ViewGroup.LayoutParams.MATCH_PARENT,
		        ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER);
		textureViewContainer.addView(MediaManager.textureView, layoutParams);
	}

	public void removeTextureView()
	{
		MediaManager.savedSurfaceTexture = null;
		if (MediaManager.textureView != null
		        && MediaManager.textureView.getParent() != null)
		{
			((ViewGroup) MediaManager.textureView.getParent())
			        .removeView(MediaManager.textureView);
		}
	}

	public void clearFullscreenLayout()
	{
		ViewGroup vp = (ViewGroup) (VideoUtils.scanForActivity(getContext()))// .getWindow().getDecorView();
		        .findViewById(Window.ID_ANDROID_CONTENT);
		View oldF = vp.findViewById(FULLSCREEN_ID);
		View oldT = vp.findViewById(TINY_ID);
		if (oldF != null)
		{
			vp.removeView(oldF);
		}
		if (oldT != null)
		{
			vp.removeView(oldT);
		}
		showSupportActionBar(getContext());
	}

	public void clearFloatScreen()
	{
		VideoUtils.getAppCompActivity(getContext())
		        .setRequestedOrientation(NORMAL_ORIENTATION);
		showSupportActionBar(getContext());
		MyVideoPlayer currJcvd = VideoPlayerManager.getCurrentJcvd();
		currJcvd.textureViewContainer.removeView(MediaManager.textureView);
		ViewGroup vp = (ViewGroup) (VideoUtils.scanForActivity(getContext()))// .getWindow().getDecorView();
		        .findViewById(Window.ID_ANDROID_CONTENT);
		vp.removeView(currJcvd);
		VideoPlayerManager.setSecondFloor(null);
	}

	public void onVideoSizeChanged()
	{
		Log.i(TAG, "onVideoSizeChanged " + " [" + this.hashCode() + "] ");
		if (MediaManager.textureView != null)
		{
			//MediaManager.textureView.setVideoSize(
			//        MediaManager.instance(getContext()).getVideoSize());
		}
	}

	public void startProgressTimer()
	{
		cancelProgressTimer();
		UPDATE_PROGRESS_TIMER = new Timer();
		mProgressTimerTask = new ProgressTimerTask();
		UPDATE_PROGRESS_TIMER.schedule(mProgressTimerTask, 0, 300);
	}

	public void cancelProgressTimer()
	{
		if (UPDATE_PROGRESS_TIMER != null)
		{
			UPDATE_PROGRESS_TIMER.cancel();
		}
		if (mProgressTimerTask != null)
		{
			mProgressTimerTask.cancel();
		}
	}

	public class ProgressTimerTask extends TimerTask
	{
		@Override
		public void run()
		{
			if (currentState == CURRENT_STATE_PLAYING
			        || currentState == CURRENT_STATE_PAUSE
			        || currentState == CURRENT_STATE_PLAYING_BUFFERING_START)
			{
				// Log.v(TAG, "onProgressUpdate " + position + "/" + duration +
				// " [" + this.hashCode() + "] ");
				mHandler.post(new Runnable()
				{
					@Override
					public void run()
					{
						int position = getCurrentPositionWhenPlaying();
						int duration = getDuration();
						int progress = position * 100
						        / (duration == 0 ? 1 : duration);
						setProgressAndText(progress, position, duration);
					}
				});
			}
		}
	}

	public void setProgressAndText(int progress, int position, int duration)
	{
		if (!mTouchingProgressBar)
		{
			if (progress != 0)
				progressBar.setProgress(progress);
		}
		if (position != 0)
			currentTimeTextView.setText(VideoUtils.stringForTime(position));
		totalTimeTextView.setText(VideoUtils.stringForTime(duration));
	}

	public void setBufferProgress(int bufferProgress)
	{
		if (bufferProgress != 0)
			progressBar.setSecondaryProgress(bufferProgress);
	}

	public void resetProgressAndTime()
	{
		progressBar.setProgress(0);
		progressBar.setSecondaryProgress(0);
		currentTimeTextView.setText(VideoUtils.stringForTime(0));
		totalTimeTextView.setText(VideoUtils.stringForTime(0));
	}

	public int getCurrentPositionWhenPlaying()
	{
		int position = 0;
		if (MediaManager.instance(getContext()).mMediaPlayer == null)
			return position;// 这行代码不应该在这，如果代码和逻辑万无一失的话，心头之恨呐
		if (currentState == CURRENT_STATE_PLAYING
		        || currentState == CURRENT_STATE_PAUSE
		        || currentState == CURRENT_STATE_PLAYING_BUFFERING_START)
		{
			try
			{
				position = (int) MediaManager
				        .instance(getContext()).mMediaPlayer
				                .getCurrentPosition();
			} catch (IllegalStateException e)
			{
				e.printStackTrace();
				return position;
			}
		}
		return position;
	}

	public int getDuration()
	{
		int duration = 0;
		if (MediaManager.instance(getContext()).mMediaPlayer == null)
			return duration;
		try
		{
			duration = (int) MediaManager.instance(getContext()).mMediaPlayer
			        .getDuration();
		} catch (IllegalStateException e)
		{
			e.printStackTrace();
			return duration;
		}
		return duration;
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar)
	{
		Log.i(TAG, "bottomProgress onStartTrackingTouch [" + this.hashCode()
		        + "] ");
		cancelProgressTimer();
		ViewParent vpdown = getParent();
		while (vpdown != null)
		{
			vpdown.requestDisallowInterceptTouchEvent(true);
			vpdown = vpdown.getParent();
		}
	}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar)
	{
		Log.i(TAG, "bottomProgress onStopTrackingTouch [" + this.hashCode()
		        + "] ");
		onEvent(UserAction.ON_SEEK_POSITION);
		startProgressTimer();
		ViewParent vpup = getParent();
		while (vpup != null)
		{
			vpup.requestDisallowInterceptTouchEvent(false);
			vpup = vpup.getParent();
		}
		if (currentState != CURRENT_STATE_PLAYING
		        && currentState != CURRENT_STATE_PAUSE)
			return;
		int time = seekBar.getProgress() * getDuration() / 100;
		MediaManager.instance(getContext()).mMediaPlayer.seekTo(time);
		Log.i(TAG, "seekTo " + time + " [" + this.hashCode() + "] ");
	}

	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
	        boolean fromUser)
	{
	}

	public void startWindowFullscreen()
	{
		Log.i(TAG, "startWindowFullscreen " + " [" + this.hashCode() + "] ");
		hideSupportActionBar(getContext());
		VideoUtils.getAppCompActivity(getContext())
		        .setRequestedOrientation(FULLSCREEN_ORIENTATION);

		ViewGroup vp = (ViewGroup) (VideoUtils.scanForActivity(getContext()))// .getWindow().getDecorView();
		        .findViewById(Window.ID_ANDROID_CONTENT);
		View old = vp.findViewById(FULLSCREEN_ID);
		if (old != null)
		{
			vp.removeView(old);
		}
		textureViewContainer.removeView(MediaManager.textureView);
		try
		{
			Constructor<MyVideoPlayer> constructor = (Constructor<MyVideoPlayer>) MyVideoPlayer.this
			        .getClass().getConstructor(Context.class);
			MyVideoPlayer jcVideoPlayer = constructor.newInstance(getContext());
			jcVideoPlayer.setId(FULLSCREEN_ID);
			LayoutParams lp = new LayoutParams(
			        ViewGroup.LayoutParams.MATCH_PARENT,
			        ViewGroup.LayoutParams.MATCH_PARENT);
			vp.addView(jcVideoPlayer, lp);
			jcVideoPlayer.setUp(urlMap, currentUrlMapIndex,
			        VideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects);
			jcVideoPlayer.setState(currentState);
			jcVideoPlayer.addTextureView();
			VideoPlayerManager.setSecondFloor(jcVideoPlayer);
			// final Animation ra = AnimationUtils.loadAnimation(getContext(),
			// R.anim.start_fullscreen);
			// jcVideoPlayer.setAnimation(ra);
			onStateNormal();
			CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public void startWindowTiny()
	{
		Log.i(TAG, "startWindowTiny " + " [" + this.hashCode() + "] ");
		onEvent(UserAction.ON_ENTER_TINYSCREEN);
		if (currentState == CURRENT_STATE_NORMAL
		        || currentState == CURRENT_STATE_ERROR)
			return;
		ViewGroup vp = (ViewGroup) (VideoUtils.scanForActivity(getContext()))// .getWindow().getDecorView();
		        .findViewById(Window.ID_ANDROID_CONTENT);
		View old = vp.findViewById(TINY_ID);
		if (old != null)
		{
			vp.removeView(old);
		}
		textureViewContainer.removeView(MediaManager.textureView);

		try
		{
			Constructor<MyVideoPlayer> constructor = (Constructor<MyVideoPlayer>) MyVideoPlayer.this
			        .getClass().getConstructor(Context.class);
			MyVideoPlayer jcVideoPlayer = constructor.newInstance(getContext());
			jcVideoPlayer.setId(TINY_ID);
			LayoutParams lp = new LayoutParams(400, 400);
			lp.gravity = Gravity.RIGHT | Gravity.BOTTOM;
			vp.addView(jcVideoPlayer, lp);
			jcVideoPlayer.setUp(urlMap, currentUrlMapIndex,
			        VideoPlayerStandard.SCREEN_WINDOW_TINY, objects);
			jcVideoPlayer.setState(currentState);
			jcVideoPlayer.addTextureView();
			VideoPlayerManager.setSecondFloor(jcVideoPlayer);
			onStateNormal();
		} catch (InstantiationException e)
		{
			e.printStackTrace();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public static void startFullscreen(Context context, Class _class,
	        String url, Object... objects)
	{
		LinkedHashMap map = new LinkedHashMap();
		map.put(URL_KEY_DEFAULT, url);
		startFullscreen(context, _class, map, 0, objects);
	}

	public static void startFullscreen(Context context, Class _class,
	        LinkedHashMap urlMap, int defaultUrlMapIndex, Object... objects)
	{
		hideSupportActionBar(context);
		VideoUtils.getAppCompActivity(context)
		        .setRequestedOrientation(FULLSCREEN_ORIENTATION);
		ViewGroup vp = (ViewGroup) (VideoUtils.scanForActivity(context))// .getWindow().getDecorView();
		        .findViewById(Window.ID_ANDROID_CONTENT);
		View old = vp.findViewById(MyVideoPlayer.FULLSCREEN_ID);
		if (old != null)
		{
			vp.removeView(old);
		}
		try
		{
			Constructor<MyVideoPlayer> constructor = _class
			        .getConstructor(Context.class);
			final MyVideoPlayer jcVideoPlayer = constructor
			        .newInstance(context);
			jcVideoPlayer.setId(MyVideoPlayer.FULLSCREEN_ID);
			LayoutParams lp = new LayoutParams(
			        ViewGroup.LayoutParams.MATCH_PARENT,
			        ViewGroup.LayoutParams.MATCH_PARENT);
			vp.addView(jcVideoPlayer, lp);
			// final Animation ra = AnimationUtils.loadAnimation(context,
			// R.anim.start_fullscreen);
			// jcVideoPlayer.setAnimation(ra);
			jcVideoPlayer.setUp(urlMap, defaultUrlMapIndex,
			        VideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN, objects);
			CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
			jcVideoPlayer.startButton.performClick();
		} catch (InstantiationException e)
		{
			e.printStackTrace();
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	// isCurrentJcvd and isCurrenPlayUrl should be two logic
	// methods,isCurrentJcvd is for different jcvd with same
	// url when fullscreen or tiny screen. isCurrenPlayUrl is to find where is
	// myself when back from tiny screen.
	// Sometimes they are overlap.
	public boolean isCurrentJcvd()
	{// 虽然看这个函数很不爽，但是干不掉
		return VideoPlayerManager.getCurrentJcvd() != null
		        && VideoPlayerManager.getCurrentJcvd() == this;
	}

	// public boolean isCurrenPlayingUrl() {
	// return url.equals(JCMediaManager.CURRENT_PLAYING_URL);
	// }

	// 退出全屏和小窗的方法
	public void playOnThisJcvd()
	{
		Log.i(TAG, "playOnThisJcvd " + " [" + this.hashCode() + "] ");
		// 1.清空全屏和小窗的jcvd
		currentState = VideoPlayerManager.getSecondFloor().currentState;
		currentUrlMapIndex = VideoPlayerManager
		        .getSecondFloor().currentUrlMapIndex;
		clearFloatScreen();
		// 2.在本jcvd上播放
		setState(currentState);
		addTextureView();
	}

	public boolean backPress()
	{
		Log.i(TAG, "backPress");
		if ((System.currentTimeMillis()
		        - CLICK_QUIT_FULLSCREEN_TIME) < FULL_SCREEN_NORMAL_DELAY)
			return false;
		((Activity) getContext()).finish();
		// if (VideoPlayerManager.getSecondFloor() != null) {
		// CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
		// MyVideoPlayer jcVideoPlayer = VideoPlayerManager.getSecondFloor();
		// jcVideoPlayer.onEvent(jcVideoPlayer.currentScreen ==
		// VideoPlayerStandard.SCREEN_WINDOW_FULLSCREEN ?
		// UserAction.ON_QUIT_FULLSCREEN :
		// UserAction.ON_QUIT_TINYSCREEN);
		// VideoPlayerManager.getFirstFloor().playOnThisJcvd();
		// return true;
		// } else if (VideoPlayerManager.getFirstFloor() != null &&
		// (VideoPlayerManager.getFirstFloor().currentScreen ==
		// SCREEN_WINDOW_FULLSCREEN ||
		// VideoPlayerManager.getFirstFloor().currentScreen ==
		// SCREEN_WINDOW_TINY)) {//以前我总想把这两个判断写到一起，这分明是两个独立是逻辑
		// CLICK_QUIT_FULLSCREEN_TIME = System.currentTimeMillis();
		// //直接退出全屏和小窗
		// VideoPlayerManager.getCurrentJcvd().currentState =
		// CURRENT_STATE_NORMAL;
		// VideoPlayerManager.getFirstFloor().clearFloatScreen();
		// MediaManager.instance(getContext()).releaseMediaPlayer();
		// VideoPlayerManager.setFirstFloor(null);
		// return true;
		// }
		return false;
	}

	public static void showSupportActionBar(Context context)
	{
		if (ACTION_BAR_EXIST)
		{
			ActionBar ab = VideoUtils.getAppCompActivity(context)
			        .getSupportActionBar();
			if (ab != null)
			{
				ab.setShowHideAnimationEnabled(false);
				ab.show();
			}
		}
		if (TOOL_BAR_EXIST)
		{
			VideoUtils.getAppCompActivity(context).getWindow()
			        .clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
		}
	}

	public static void hideSupportActionBar(Context context)
	{
		if (ACTION_BAR_EXIST)
		{
			ActionBar ab = VideoUtils.getAppCompActivity(context)
			        .getSupportActionBar();
			if (ab != null)
			{
				ab.setShowHideAnimationEnabled(false);
				ab.hide();
			}
		}
		if (TOOL_BAR_EXIST)
		{
			VideoUtils.getAppCompActivity(context).getWindow().setFlags(
			        WindowManager.LayoutParams.FLAG_FULLSCREEN,
			        WindowManager.LayoutParams.FLAG_FULLSCREEN);
		}
	}

	public static long lastAutoFullscreenTime = 0;

	// 重力感应的时候调用的函数，
	public void autoFullscreen(float x)
	{
		if (isCurrentJcvd() && currentState == CURRENT_STATE_PLAYING
		        && currentScreen != SCREEN_WINDOW_FULLSCREEN
		        && currentScreen != SCREEN_WINDOW_TINY)
		{
			if (x > 0)
			{
				VideoUtils.getAppCompActivity(getContext())
				        .setRequestedOrientation(
				                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
			}
			else
			{
				VideoUtils.getAppCompActivity(getContext())
				        .setRequestedOrientation(
				                ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
			}
			onEvent(UserAction.ON_ENTER_FULLSCREEN);
			startWindowFullscreen();
		}
	}

	public void autoQuitFullscreen()
	{
		if ((System.currentTimeMillis() - lastAutoFullscreenTime) > 2000
		        && isCurrentJcvd() && currentState == CURRENT_STATE_PLAYING
		        && currentScreen == SCREEN_WINDOW_FULLSCREEN)
		{
			lastAutoFullscreenTime = System.currentTimeMillis();
			backPress();
		}
	}

	public static class JCAutoFullscreenListener implements SensorEventListener
	{
		@Override
		public void onSensorChanged(SensorEvent event)
		{// 可以得到传感器实时测量出来的变化值
			final float x = event.values[SensorManager.DATA_X];
			float y = event.values[SensorManager.DATA_Y];
			float z = event.values[SensorManager.DATA_Z];
			// 过滤掉用力过猛会有一个反向的大数值
			if (((x > -15 && x < -10) || (x < 15 && x > 10))
			        && Math.abs(y) < 1.5)
			{
				if ((System.currentTimeMillis()
				        - lastAutoFullscreenTime) > 2000)
				{
					if (VideoPlayerManager.getCurrentJcvd() != null)
					{
						VideoPlayerManager.getCurrentJcvd().autoFullscreen(x);
					}
					lastAutoFullscreenTime = System.currentTimeMillis();
				}
			}
		}

		@Override
		public void onAccuracyChanged(Sensor sensor, int accuracy)
		{
		}
	}

	public static void clearSavedProgress(Context context, String url)
	{
		VideoUtils.clearSavedProgress(context, url);
	}

	public static void setJcUserAction(UserAction jcUserEvent)
	{
		JC_USER_EVENT = jcUserEvent;
	}

	public void onEvent(int type)
	{
		if (JC_USER_EVENT != null && isCurrentJcvd() && urlMap != null)
		{
			JC_USER_EVENT.onEvent(type,
			        VideoUtils.getCurrentUrlFromMap(urlMap, currentUrlMapIndex),
			        currentScreen, objects);
		}
	}

	public AudioManager.OnAudioFocusChangeListener onAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener()
	{
		@Override
		public void onAudioFocusChange(int focusChange)
		{
			switch (focusChange)
			{
				case AudioManager.AUDIOFOCUS_GAIN:
					break;
				case AudioManager.AUDIOFOCUS_LOSS:
					releaseAllVideos();
					Log.d(TAG, "AUDIOFOCUS_LOSS [" + this.hashCode() + "]");
					break;
				case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
					try
					{
						if (MediaManager
						        .instance(getContext()).mMediaPlayer != null
						        && MediaManager
						                .instance(getContext()).mMediaPlayer
						                        .isPlaying())
						{
							MediaManager.instance(getContext()).mMediaPlayer
							        .pause();
						}
					} catch (IllegalStateException e)
					{
						e.printStackTrace();
					}
					Log.d(TAG, "AUDIOFOCUS_LOSS_TRANSIENT [" + this.hashCode()
					        + "]");
					break;
				case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
					break;
			}
		}
	};

	// TODO 是否有用
	public void onSeekComplete()
	{

	}

	public void showWifiDialog(int event)
	{
	}

	public void showProgressDialog(float deltaX, String seekTime,
	        int seekTimePosition, String totalTime, int totalTimeDuration)
	{
	}

	public void dismissProgressDialog()
	{

	}

	public void showVolumeDialog(float deltaY, int volumePercent)
	{

	}

	public void dismissVolumeDialog()
	{

	}

	public void showBrightnessDialog(int brightnessPercent)
	{

	}

	public void dismissBrightnessDialog()
	{

	}

}
